import { getVerifyDataByFormula, generateVerifyDataByFormula, getCpasTableDataByTzTypeAPI, } from "../api/DesignTableApi";
/**
 * 公式类型枚举: 1.表内校验 2.表间校验 3.与报表校验 4.交叉校验
 */
export var artVerifyFormulaType;
(function (artVerifyFormulaType) {
    artVerifyFormulaType["IN_V"] = "1";
    artVerifyFormulaType["OUT_V"] = "2";
    artVerifyFormulaType["FS_V"] = "3";
    artVerifyFormulaType["CROSS_V"] = "4";
})(artVerifyFormulaType || (artVerifyFormulaType = {}));
/**
 * 校验结果描述枚举 1. 逻辑不符 2. 差异数 3. 无法校验
 */
export var artVerifyResultType;
(function (artVerifyResultType) {
    artVerifyResultType["LOGIC_NOT_MATCH"] = "1";
    artVerifyResultType["DIFFERENT"] = "2";
    artVerifyResultType["UNABLE_TO_VERIFY"] = "3";
})(artVerifyResultType || (artVerifyResultType = {}));
/**
 * 勾稽校验服务
 *  1. 提供解析勾稽校验公式逻辑解析服务
 *  2. 存储勾稽校验公式
 *  3. 存储勾稽校验公式逻辑解析数据
 *  4. 提供勾稽校验结果标注服务（在单元格上标记校验和被校验）
 *
 *  命名简写：
 *  articulation (勾稽关系) : 在函数中简写为 art
 *
 */
export default class ArticulationVerifyService {
    context;
    constructor(context) {
        this.context = context;
    }
    get headerService() {
        return this.context.headerService;
    }
    get hot() {
        return this.context.hot;
    }
    get hyper() {
        return this.context.hyper;
    }
    get formulaService() {
        return this.context.formulaService;
    }
    get tagService() {
        return this.context.tagService;
    }
    get hyperFormulaService() {
        return this.context.hyperFormulaService;
    }
    destroy() {
        this.context = null;
    }
    artResultItem = [];
    //本表勾稽校验公式
    artVerifyFormulaList = [];
    //勾稽校验公式解析结果
    artParseResultList = [];
    //非本表勾稽校验公式
    otherArtVerifyFormulaList = [];
    //本表勾稽校验母公式下DynamicMaps数据(只存储还原操作后的母公式数据，兼容后端，需要删除非本表的数据) "[{\"tid\":\"ecc42de34ab15383\",\"id\":\"BgwBeLT0kC\"},{\"tid\":\"ecc42de34ab15383\",\"id\":\"r_CLTaMGPx\"}]"
    parentDynamicMaps;
    /**
     * 清空勾稽标注
     */
    clearArtVerifyMark() {
        let ref = this.context;
        if (this.context.props.type === "zl") {
            const cpasTableRefs = this.context.cpasTableRefs;
            for (let i = 0; i < cpasTableRefs.length; i++) {
                const cpasTableRef = cpasTableRefs[i];
                f(cpasTableRef);
            }
        }
        else {
            f(ref);
        }
        function f(ref) {
            ref.gridService.clearCellMetaCustomInfo(["verify", "beVerified"], ref.cellMetaData);
            const cellsMeta = ref.hot.getCellsMeta();
            for (let i = 0; i < cellsMeta.length; i++) {
                const cellMeta = cellsMeta[i];
                if (cellMeta["custom"] && cellMeta["custom"]["verify"]) {
                    delete cellMeta["custom"]["verify"];
                }
                if (cellMeta["custom"] && cellMeta["custom"]["beVerified"]) {
                    delete cellMeta["custom"]["beVerified"];
                }
                if (cellMeta["comment"]) {
                    delete cellMeta["comment"];
                }
            }
            ref.hot.render();
        }
    }
    /**
     * 获取勾稽校验总体结果
     */
    getArtVerifyResult() {
        const artParseResultList = this.artParseResultList;
        const result = artParseResultList.every((item) => {
            return item.fullFormulaResult;
        });
        return result;
    }
    //判断cmap中是否包含name
    getDataByCmapName(arr, name) {
        let isTrue = false;
        if (!arr || !arr.length) {
            return isTrue;
        }
        for (let i = 0; i < arr.length; i++) {
            const cmap = arr[i];
            if (typeof cmap === "string" && cmap.endsWith(name)) {
                isTrue = true;
            }
        }
        return isTrue;
    }
    /**
     * 解析勾稽校验公式,返回artVerifyFormulaParseResult集合
     */
    async parseArtVerifyFormula(formulas, dsRef) {
        //存储校验公式
        this.artVerifyFormulaList = formulas;
        let artVerifyFormulaParseResultList = [];
        let getSourceData = this.context.hot.getSourceData();
        let getData = this.context.hot.getData();
        let tid = this.context?.props?.notes?.tid || "";
        let type = this.context?.props?.type || "";
        const headerData = dsRef
            ? dsRef.headerService.headJson
            : this.context?.headerService.headJson;
        const cellsMeta = dsRef ? dsRef.filterMetas() : this.context?.filterMetas();
        const tableConfig = dsRef ? dsRef.tableConfig : this.context?.tableConfig;
        //支持附注模式下校验公式计算
        if (dsRef) {
            getSourceData = dsRef.hot.getSourceData();
            getData = dsRef.hot.getData();
            tid = dsRef?.props?.notes?.tid;
            type = dsRef?.props?.type;
        }
        try {
            const isCmapResult = this.getDataByCmapName(getData[0], "tzh");
            if (isCmapResult) {
                // 调整后数调用
                const tzhIGridParam = {
                    header: headerData,
                    data: getSourceData,
                    displayData: getData,
                    cellsMeta,
                    tableConfig,
                };
                const tzhGridData1 = (await getCpasTableDataByTzTypeAPI({
                    iGridData: tzhIGridParam,
                    tzType: "tzh",
                })).data;
                if (tzhGridData1) {
                    getSourceData = tzhGridData1?.data;
                    getData = tzhGridData1?.displayData;
                }
            }
            const headerColumn = this.context.headerService.getHeaderColumn(headerData);
            const response = await getVerifyDataByFormula(getSourceData, getData, formulas, tid, type, headerColumn);
            if (response.code === 200) {
                artVerifyFormulaParseResultList = response.data;
            }
        }
        catch (e) {
            console.error(e.message);
        }
        //存储校验公式结果
        this.artParseResultList = artVerifyFormulaParseResultList;
        return artVerifyFormulaParseResultList;
    }
    /**
     * 生成钩稽校验公式，返回artVerifyFormulaParseResult集合
     */
    async generateArtVerifyFormula(formulas, tid) {
        let artVerifyFormulaGenerateResultList = [];
        try {
            const headerData = this.context?.headerService.headJson;
            const headerColumn = this.context.headerService.getHeaderColumn(headerData);
            let getData = this.context.hot.getData();
            const response = await generateVerifyDataByFormula(formulas, tid, {
                displayData: getData,
                headerColumn,
            });
            if (response.code === 200) {
                artVerifyFormulaGenerateResultList = response.data;
            }
        }
        catch (e) {
            console.error(e.message);
        }
        return artVerifyFormulaGenerateResultList;
    }
    /**
     * 格式化动态生成的校验公式,并返回父公式和子公式
     * 返回母公式，本表子公式，非本表子公式
     */
    formatDynamicFormula(artVerifyFormulaGenerateList, tid) {
        if (!artVerifyFormulaGenerateList || !artVerifyFormulaGenerateList.length) {
            return;
        }
        let parentFormula = [];
        let childFormula = [];
        let otherChildFormula = [];
        for (let i = 0; i < artVerifyFormulaGenerateList.length; i++) {
            const { formula, generateInfo } = artVerifyFormulaGenerateList[i];
            if (formula) {
                parentFormula.push({
                    ...formula,
                });
            }
            if (Array.isArray(generateInfo)) {
                for (let j = 0; j < generateInfo.length; j++) {
                    const currentChild = generateInfo[j];
                    if (currentChild?.tid === tid) {
                        childFormula.push({
                            ...currentChild.artVerifyFormulaItem,
                            // number: j + 1,
                            tid: currentChild?.tid,
                        });
                    }
                    else {
                        otherChildFormula.push({
                            ...currentChild.artVerifyFormulaItem,
                            // number: j + 1,
                            tid: currentChild?.tid,
                        });
                    }
                }
            }
        }
        if (otherChildFormula && otherChildFormula.length) {
            this.otherArtVerifyFormulaList = otherChildFormula;
        }
        return {
            parentFormula,
            childFormula,
            otherChildFormula,
        };
    }
    /**
     * 批量标注被校验项
     */
    batchMarkBeVerifiedItem(artParseResultList) {
        if (this.artParseResultList.length === 0) {
            console.error("未检测到,存储的校验结果 artParseResultList");
            return;
        }
        //标注前清空所有标注
        this.clearArtVerifyMark();
        for (let i = 0; i < artParseResultList.length; i++) {
            const result = artParseResultList[i];
            //批量标注被校验时，只标记被校验项目。并且只标记校验结果出错的
            this.markBeVerifiedItem(result, false, true);
        }
    }
    /**
     * 根据坐标返回标注的被校验项
     */
    getBeVerifiedItemByCoords(coords) {
        const getMarkType = "beVerified";
        const { row, col } = coords;
        const metaInfo = this.context.hot.getCellMeta(row, col);
        const artInfo = (metaInfo["custom"] && metaInfo["custom"][getMarkType]) || null;
        return artInfo;
    }
    /**
     * 被校验项标注
     * 标记需求:
     * 1. 初始化的时候会根据存储的校验结果进行整体的一次标记->只标记全部被校验项.被校验项需要做重叠处理 ✅  batchMarkBeVerifiedItem
     * 2. 从详情里面选择任何一个校验公式时，->标记被校验项和校验项 , ->如果校验项和被校验项重叠则被校验项优先不标记校验项 ✅ markBeVerifiedItem
     * 3. 被校验项身上存在两种操作方式，一个是tip展示身上具备哪些公式。是哪些被校验项的因子 -> tip中只展示公式序号. 另一个是通过被校验项公式能筛选出哪些被校验项中包含该因子展示到详情中
     * 4. 交叉校验仅标注成对的 ✅
     *
     * result : 单个校验公式的解析结果
     * isMarkVerifyItem : 是否标记校验项,默认为true进行标记, 如果是校验项只标记IN_CELL公式. 默认为true
     * isOnlyShowResultFalse: 是否只展示校验结果为false的校验项,默认为false
     */
    markBeVerifiedItem(result, isMarkVerifyItem = true, isOnlyShowResultFalse = false) {
        const { type } = result;
        if (type === artVerifyFormulaType.CROSS_V) {
            //bydingxiaofei1120 跟兴哥讨论后，交叉校验解析完要按照表内校验标记
            const crossResult = {
                ...result,
                type: "1",
            };
            this.markStandardVerifyItem(crossResult, isMarkVerifyItem, isOnlyShowResultFalse);
            // this.markCrossVerifiedItem(
            //   result as artCrossVerifyFormulaParseResult,
            //   isMarkVerifyItem,
            //   isOnlyShowResultFalse
            // );
        }
        else {
            this.markStandardVerifyItem(result, isMarkVerifyItem, isOnlyShowResultFalse);
        }
    }
    /**
     * 交叉校验/被校验项目标注
     */
    markCrossVerifiedItem(parseResult, isMarkVerifyItem = true, isOnlyShowResultFalse = false) {
        const { beVerifiedFormulaResultList } = parseResult;
        const artVerifyMarkItemList = [];
        beVerifiedFormulaResultList.forEach((item, index) => {
            if (item) {
                const { coords, result, formula, value } = item;
                const artVerifyMarkItem = {
                    coords,
                    result,
                    type: artVerifyFormulaType.CROSS_V,
                    fullFormula: parseResult.fullFormula,
                    beVerifiedFormula: formula,
                    beVerifiedFormulaResult: value,
                    number: parseResult.number,
                    isForce: parseResult.isForce,
                    verifyItem: item.verifyItem,
                    currentFormula: formula,
                };
                artVerifyMarkItemList.push(artVerifyMarkItem);
            }
        });
        this.markCell(artVerifyMarkItemList, "beVerified", isMarkVerifyItem, isOnlyShowResultFalse);
    }
    /**
     * 标准类型校验/被校验项标注
     */
    markStandardVerifyItem(parseResult, isMarkVerifyItem = true, isOnlyShowResultFalse = false) {
        const { beVerifiedCoordsMap, fullFormulaResult, type, beVerifiedFormula, beVerifiedFormulaResult, verifyFormulaList, fullFormula, } = parseResult;
        const artBeVerifiedMarkItemList = [];
        for (let formula in beVerifiedCoordsMap) {
            const coords = beVerifiedCoordsMap[formula];
            if (coords) {
                const artVerifyMarkItem = {
                    coords,
                    result: fullFormulaResult,
                    type: type,
                    fullFormula,
                    beVerifiedFormula,
                    beVerifiedFormulaResult,
                    number: parseResult.number,
                    isForce: parseResult.isForce,
                    currentFormula: formula,
                };
                artBeVerifiedMarkItemList.push(artVerifyMarkItem);
            }
        }
        //被校验项标注
        this.markCell(artBeVerifiedMarkItemList, "beVerified", isMarkVerifyItem, isOnlyShowResultFalse);
        //校验项标注
        if (isMarkVerifyItem) {
            const artVerifyMarkItemList = [];
            verifyFormulaList.forEach((item) => {
                if (item.coords) {
                    artVerifyMarkItemList.push({
                        coords: item.coords,
                        result: fullFormulaResult,
                        type: parseResult.type,
                        fullFormula,
                        beVerifiedFormula,
                        beVerifiedFormulaResult,
                        number: parseResult.number,
                        isForce: parseResult.isForce,
                        currentFormula: item.currentFormula,
                    });
                }
            });
            this.markCell(artVerifyMarkItemList, "verify", isMarkVerifyItem, isOnlyShowResultFalse);
        }
    }
    /**
     * 设置单元格标注信息
     */
    setCellMetaArtInfo(rmap, cmap, key, value, ref) {
        const row = ref.gridService.getRowIndexByRmap(rmap);
        const col = ref.gridService.getColumnIndexByCmap(cmap);
        if (!(row && col)) {
            return;
        }
        const metaInfo = ref.hot.getCellMeta(row, col);
        const artInfo = metaInfo["custom"] && metaInfo["custom"][key];
        if (artInfo && Array.isArray(artInfo)) {
            //如果存在重叠标记的情况开启，注释模式.
            artInfo.push(value);
            this.showCommentMode(row, col, artInfo, ref);
        }
        else {
            ref.gridService.setCellMetaCustomInfo(row, col, key, [
                {
                    ...value,
                },
            ], ref, true);
        }
    }
    /**
     * 单个单元格标注
     */
    markSingleCell(rmap, cmap) {
        const row = this.context.gridService.getRowIndexByRmap(rmap);
        const col = this.context.gridService.getColumnIndexByCmap(cmap);
        if (row && col) {
            this.context.gridService.setCellMetaCustomInfo(row, col, "verify", true);
            this.hot.render();
        }
        else {
            return "单元格不存在";
        }
    }
    /**
     * 注释模式展示
     */
    showCommentMode(row, col, artInfo, ref) {
        let value = "公式序号:";
        const formulaNumberList = [];
        artInfo.forEach((item) => {
            const { result, type, number } = item;
            formulaNumberList.push(number);
        });
        value += formulaNumberList.join(",");
        ref.hot.setCellMeta(row, col, "comment", {
            value: value,
            readOnly: true,
        });
    }
    /**
     * 单元格批量标注
     */
    markCell(rtVerifyMarkItemList, markType, isMarkVerifyItem = true, isOnlyShowResultFalse = false) {
        if (rtVerifyMarkItemList.length <= 0) {
            return;
        }
        let ref = this.context;
        if (this.context.props.type === "zl") {
            const cpasTableRefs = this.context.cpasTableRefs;
            for (let i = 0; i < cpasTableRefs.length; i++) {
                const cpasTableRef = cpasTableRefs[i];
                this.markCellByRef(rtVerifyMarkItemList, markType, isMarkVerifyItem, isOnlyShowResultFalse, cpasTableRef);
            }
        }
        else {
            this.markCellByRef(rtVerifyMarkItemList, markType, isMarkVerifyItem, isOnlyShowResultFalse, ref);
        }
    }
    /**
     * 标记
     */
    markCellByRef(rtVerifyMarkItemList, markType, isMarkVerifyItem, isOnlyShowResultFalse, ref) {
        if (!ref) {
            console.error("ref is null");
            return;
        }
        rtVerifyMarkItemList.forEach((item) => {
            const { coords, result, type } = item;
            const { row, col, rmap, cmap } = coords;
            //标准校验项标记
            if (markType === "verify" &&
                type !== artVerifyFormulaType.CROSS_V &&
                isMarkVerifyItem) {
                console.warn(`标注校验项 ${rmap} ${cmap}`);
                console.warn(ref.props.name);
                this.setCellMetaArtInfo(rmap, cmap, "verify", item, ref);
                return false;
            }
            //成对标记）需求决定。不会将校验项都标记出来的需求
            if (type === artVerifyFormulaType.CROSS_V &&
                isMarkVerifyItem &&
                !(isOnlyShowResultFalse && result)) {
                const { verifyItem } = item;
                //关联的校验项标记
                const { row: verifyRow, col: verifyCol, rmap: verifyRMap, cmap: verifyCMap, } = verifyItem.coords;
                console.warn(`标注交叉校验，校验项 ${verifyRMap} ${verifyCMap}`);
                console.warn(ref.props.name);
                this.setCellMetaArtInfo(verifyRMap, verifyCMap, "verify", item, ref);
            }
            //只有当被校验项校验结果为false时进行标注
            if (isOnlyShowResultFalse && result) {
                return false;
            }
            console.warn(`标注被校验项，校验项 ${rmap} ${cmap}`);
            console.warn(ref.props.name);
            //被校验项标注始终会标注
            this.setCellMetaArtInfo(rmap, cmap, "beVerified", item, ref);
            //校验项标记
        });
        ref.hot.render();
    }
}
